package com.dmall.promotion.useraop.handler.context;

import com.dmall.promotion.annotation.ListenUserOperation;
import com.dmall.promotion.enums.UserOperationEnum;
import com.dmall.promotion.useraop.handler.AbsUserOperationHandler;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * handler上下文对象
 * 获取handler的
 * @author xiao1.wang
 * @date 2021-06-03 22:17:05
 */
@Component
public class UserOperationHandlerContext implements ApplicationContextAware {

    private final EnumMap<UserOperationEnum, List<AbsUserOperationHandler>> syncHandlerMap = new EnumMap<>(UserOperationEnum.class);
    private final EnumMap<UserOperationEnum, List<AbsUserOperationHandler>> asyncHandlerMap = new EnumMap<>(UserOperationEnum.class);

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        LinkedHashMap<ListenUserOperation, AbsUserOperationHandler> operationHandlerMap = new LinkedHashMap<>();
        String[] beanNames = applicationContext.getBeanNamesForType(AbsUserOperationHandler.class);
        // String[] beanNames = applicationContext.getBeanNamesForAnnotation(ListenUserOperation.class);
        for (String beanName : beanNames) {
            AbsUserOperationHandler handler = (AbsUserOperationHandler) applicationContext.getBean(beanName);
            ListenUserOperation annotation = handler.getClass().getAnnotation(ListenUserOperation.class);
            operationHandlerMap.put(annotation, handler);
        }

        List<Map.Entry<ListenUserOperation, AbsUserOperationHandler>> handlerMapList = new ArrayList<>(operationHandlerMap.entrySet());
        // 排序
        handlerMapList.sort(Comparator.comparingInt(e -> e.getKey().order()));

        for (Map.Entry<ListenUserOperation, AbsUserOperationHandler> entry : handlerMapList) {
            ListenUserOperation operation = entry.getKey();
            AbsUserOperationHandler handler = entry.getValue();
            UserOperationEnum[] operationEnums = operation.value();
            boolean sync = operation.sync();
            if (sync) {
                for (UserOperationEnum operationEnum : operationEnums) {
                    List<AbsUserOperationHandler> handlers = syncHandlerMap.computeIfAbsent(operationEnum, k -> new ArrayList<>());
                    handlers.add(handler);
                }
            } else {
                for (UserOperationEnum operationEnum : operationEnums) {
                    List<AbsUserOperationHandler> handlers = asyncHandlerMap.computeIfAbsent(operationEnum, k -> new ArrayList<>());
                    handlers.add(handler);
                }
            }
        }
    }

    /**
     * 根据操作类型按优先级返回同步执行的handler集合
     * @param operationEnum 操作类型
     * @return handler集合
     */
    public List<AbsUserOperationHandler> getSyncHandlers(UserOperationEnum operationEnum) {
        return syncHandlerMap.get(operationEnum);
    }

    /**
     * 根据操作类型按优先级返回异步执行的handler集合
     * @param operationEnum 操作类型
     * @return handler集合
     */
    public List<AbsUserOperationHandler> getAsyncHandlers(UserOperationEnum operationEnum) {
        return asyncHandlerMap.get(operationEnum);
    }
}
